#ifndef _FMVC_REQUEST_HANDLER_
#define _FMVC_REQUEST_HANDLER_

#include <sstream>

#include <fcgiapp.h>

#include <boost/unordered_map.hpp>

#include "BaseHandler.h"
#include "Params.h"

namespace FMVC
{
  class RequestHandler
  {  
    private:
      typedef boost::unordered_map<std::string,BaseHandler*> map;
      map _handlerMap;
      int socket;

      static RequestHandler* instance;

      RequestHandler()
      {
        FCGX_Init();
        socket = FCGX_OpenSocket(":32910",100);
      }

    public:

      ~RequestHandler()
      {
        FCGX_Finish();
      };

      static RequestHandler* GetInstance()
      {
        if (instance == NULL)
          instance = new RequestHandler();
        return instance;
      }

      void Run()
      {
        FCGX_Request request;
        FCGX_InitRequest(&request,socket,0);
        for (;FCGX_Accept_r(&request) == 0; FCGX_Finish_r(&request) )
        {      
          Params env(request);
          std::string requestUri = env.GetRequestUri();
          std::string trimUri = requestUri.substr(0,requestUri.find("?"));
          std::ostringstream outContent;
          std::ostringstream outHeaders;


          if (_handlerMap[trimUri] == NULL)
            DefaultPage(outContent);
          else
            _handlerMap[trimUri]->Proccess(outHeaders,outContent,env);   
               
          outHeaders << "Content-Length: " << outContent.str().length() << "\r\n\r\n";
          FCGX_PutStr(outHeaders.str().c_str(),outHeaders.str().length(),request.out);
          FCGX_PutStr(outContent.str().c_str(),outContent.str().length(),request.out);
        }
      }


      void DefaultPage(std::ostream &out)
      {
        const char* defaultPage = "<html>"
          "404"
          "</html>";
        out << "Content-type: text/html\r\n\r\n";
        out << defaultPage;
      }

      template <typename H>
        void AddHandler(const char *uri)
        {
          _handlerMap[ std::string(uri) ] = new H();
        };

  };

  RequestHandler* RequestHandler::instance = NULL;
};
#endif
